﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;

using Cinch;
using MEFedMVVM.ViewModelLocator;
using MEFedMVVM.Services.Contracts;
using MEFedMVVM.Common;
using System.Windows.Threading;
using System.Threading;
using System.Configuration;


namespace Anata.Client
{
    /// <summary>
    /// This is a workspace type ViewModel, which is created by some code in the <c>MainWindowViewModel</c>
    /// and the DataTemplate in the <c>MainWindow.xaml</c>
    /// 
    /// This is the main ViewModel of the demo app, and this ViewModel makes use
    /// of pretty much all the Cinch services available.
    /// 
    /// This ViewModel is also able to operate in design mode by using the
    /// <c>IImageProvider</c> data service, which can either be a runtime service or a design time service
    /// 
    /// This ViewModel is also expecting some contextual data from the <c>IViewAwareStatus</c> service
    /// (as we are using a View 1st type of development in CinchV2). This contextual data is the
    /// image path that the <c>IImageProvider</c> data service uses to fetch images.
    /// 
    /// As such this ViewModel expects the <c>IViewAwareStatus</c> service which allows the ViewModel
    /// to examine this contextual view data
    /// 
    /// Anyway in this ViewModel you will find a demo of most of the services Cinch has to offer
    /// </summary>
    [ExportViewModel("TransaksiListViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class TransaksiListViewModel : ViewModelBase
    {
        #region Data
        //private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private String filterKeyword = "";

        private bool isAllLoaded = false;
        private int pageLoaded = 0;
        private DispatcherTimer filterTimer;
        #endregion

        //private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
        
        #region Data.Rules
        #endregion
        
        #region Data.VMs
        private DispatcherNotifiedObservableCollection<TransaksiThumbnailViewModel> transaksis;
        private ICollectionView transaksisCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private ITransaksiProvider transaksiProvider;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public TransaksiListViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IViewAwareStatus viewAwareStatusService,
            ITransaksiProvider transaksiProvider,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.viewAwareStatusService = viewAwareStatusService;
            this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            this.transaksiProvider = transaksiProvider;
            this.referenceProvider = referenceProvider;
            #endregion

            #region Constructor.SetupCommands
            TransaksiBaruCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiBaruCommand, ExecuteTransaksiBaruCommand);
            TransaksiRefreshCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiRefreshCommand, ExecuteTransaksiRefreshCommand);
            TransaksiSelectCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiSelectCommand, ExecuteTransaksiSelectCommand);
            TransaksiFilterKeyUpCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiFilterKeyUpCommand, ExecuteTransaksiFilterKeyUpCommand);
            //TransaksiFilterKeyUpCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiFilterKeyUpCommand, ExecuteTransaksiFilterKeyUpCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            #endregion

            #region Constructor.SetupValidationRules
            #endregion

            #region Constructor.SetupVMs
            Transaksis = new DispatcherNotifiedObservableCollection<TransaksiThumbnailViewModel>();
            TransaksisCV = CollectionViewSource.GetDefaultView(transaksis);
            //TransaksisCV.SortDescriptions.Add(new SortDescription("StatusTransaksi", ListSortDirection.Ascending));
            #endregion

            Mediator.Instance.Register(this);

            #region Constructor.Filter
            filterTimer = new DispatcherTimer();
            filterTimer.Interval = TimeSpan.FromMilliseconds(
                Int32.Parse(ConfigurationManager.AppSettings["FilterResponsiveness"].ToString()));
            filterTimer.Tick += new EventHandler(LazyFilterCallback);
            #endregion
        }
        #endregion

        #region Public Properties

        #region Public.Commands
        public SimpleCommand<Object, Object> TransaksiBaruCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiRefreshCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiFilterKeyUpCommand { get; private set; }
        public SimpleCommand<Object, Object> TransaksiSelectCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs transaksisChangeArgs =
            ObservableHelper.CreateArgs<TransaksiListViewModel>(x => x.Transaksis);
        public DispatcherNotifiedObservableCollection<TransaksiThumbnailViewModel> Transaksis
        {
            get { return transaksis; }
            set
            {
                transaksis = value;
                NotifyPropertyChanged(transaksisChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs transaksisCVChangeArgs =
            ObservableHelper.CreateArgs<TransaksiListViewModel>(x => x.TransaksisCV);
        public ICollectionView TransaksisCV
        {
            get { return transaksisCV; }
            set
            {
                transaksisCV = value;
                NotifyPropertyChanged(transaksisCVChangeArgs);
            }
        }



        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs filterKeywordChangeArgs =
            ObservableHelper.CreateArgs<TransaksiListViewModel>(x => x.FilterKeyword);
        public String FilterKeyword
        {
            get { return filterKeyword; }
            set
            {
                filterKeyword = value;
                NotifyPropertyChanged(filterKeywordChangeArgs);
                LazyFilter();
            }
        }
        #endregion

        #region Public.CachedCollection
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiBaruCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiBaruCommand(Object args)
        {
            TransaksiThumbnailViewModel ttvm = new TransaksiThumbnailViewModel();
            transaksis.Add(ttvm);
            Mediator.Instance.NotifyColleagues<TransaksiThumbnailViewModel>(
                "TryActivateTransaksiDetail", ttvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiRefreshCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiRefreshCommand(Object args)
        {
            pageLoaded = 0;
            isAllLoaded = false;
            transaksis.Clear();
            transaksiProvider.LazyFetchTransaksis(pageLoaded, PostLoadTransaksis);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiFilterKeyUpCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiFilterKeyUpCommand(Object args)
        {
            //EventToCommandArgs eventArgs = args as EventToCommandArgs;
            //TextBox tb = eventArgs.Sender as TextBox;
            //LazyFilter(tb.Text);
            //NotifyPropertyChanged(filterKeywordChangeArgs);
            LazyFilter();
        }
        
        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiSelectCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiSelectCommand(Object args)
        {
            TransaksiThumbnailViewModel ttvm = (TransaksiThumbnailViewModel)TransaksisCV.CurrentItem;
            if (ttvm != null)
            {
                Mediator.Instance.NotifyColleagues<TransaksiThumbnailViewModel>(
                    "TryActivateTransaksiDetail", ttvm);
            }
        }

        #endregion

        #region Mediator Message Sinks
        [MediatorMessageSink("RemoveTransaksiThumbnail")]
        private void RemoveTransaksiThumbnail(TransaksiThumbnailViewModel ttvm)
        {
            if (this.transaksis.Contains(ttvm))
            {
                this.transaksis.Remove(ttvm);
            }
        }

        [MediatorMessageSink("TryHighlightTransaksiThumbnail")]
        private void TryHighlightTransaksiThumbnail(TransaksiThumbnailViewModel ttvm)
        {
            if (this.transaksisCV.Contains(ttvm) && !ttvm.Equals(this.transaksisCV.CurrentItem))
            {
                this.transaksisCV.MoveCurrentTo(ttvm);
                Console.WriteLine("posisi #" + TransaksisCV.CurrentPosition + ": " + TransaksisCV.CurrentItem);
            }
        }

        [MediatorMessageSink("TryCancelTransaksiThumbnail")]
        private void TryCancelTransaksiThumbnail(TransaksiThumbnailViewModel ttvm)
        {
            if (this.TransaksisCV.Contains(ttvm))
            {
                if (ttvm.IdTransaksi != 0)
                {
                    CustomDialogResults result = messageBoxService.ShowYesNo("Yakin Batalkan?", CustomDialogIcons.Question);
                    if (result == CustomDialogResults.Yes)
                    {
                        ttvm.IsBatal = true;
                        ttvm.WaktuSelesai = DateTime.Now;
                        transaksiProvider.LazySaveTransaksi(ttvm, PostCancelTransaksi);
                    }
                }
                else
                {
                    transaksis.Remove(ttvm);
                }
            }
        }

        [MediatorMessageSink("TryPayTransaksiThumbnail")]
        private void TryPayTransaksiThumbnail(TransaksiThumbnailViewModel ttvm)
        {
            if (this.TransaksisCV.Contains(ttvm))
            {
                TransaksiViewModel tvm = new TransaksiViewModel(
                    messageBoxService,
                    uiVisualizerService,
                    viewAwareStatusService,
                    transaksiProvider,
                    referenceProvider);
                bool? result = uiVisualizerService.ShowDialog("TransaksiPayPopup", tvm);
                if (result.HasValue && result.Value)
                {
                    ttvm.WaktuSelesai = DateTime.Now;
                }
            }
        }

        [MediatorMessageSink("TryRefreshTransaksiThumbnail")]
        private void TryRefreshTransaksiThumbnail(int idTransaksi)
        {
            try 
	        {
                TransaksiThumbnailViewModel ttvm = transaksis.First(t => t.IdTransaksi == idTransaksi);
                if (!ttvm.IsBusy)
                {
                    ttvm.IsBusy = true;
                    Dispatcher.CurrentDispatcher.InvokeIfRequired(() =>
                    {
                        transaksiProvider.LazyLoadTransaksi(ttvm, PostLoadTransaksi);
                    }, DispatcherPriority.Background); 
                }
	        }
	        catch (Exception) {}
        }
        #endregion

        #region PrivateMethods
        #region PrivateMethods.ViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            transaksiProvider.LazyFetchTransaksis(pageLoaded, PostLoadTransaksis);
        }
        #endregion

        #region PrivateMethods.Filter
        private void LazyFilter()
        {
            filterTimer.Stop();
            filterTimer.Start();
        }
        private void LazyFilterCallback(object sender, EventArgs e)
        {
            Console.WriteLine("stopped typing, filtering with keyword: " + filterKeyword);
            filterTimer.Stop();
            if (filterKeyword != "")
            {
                transaksisCV.Filter = new Predicate<object>(LazyFilterPredicate);
            }
            else
            {
                transaksisCV.Filter = null;
            }
        }
        private bool LazyFilterPredicate(object row)
        {
            TransaksiThumbnailViewModel ttvm = row as TransaksiThumbnailViewModel;
            return (ttvm.NamaKonsumen.ToLower().Contains(filterKeyword.ToLower()));
        }
        #endregion

        #region PrivateMethods.PostLoader
        /// <summary>
        /// post loader
        /// </summary>
        private void PostLoadTransaksi(TransaksiThumbnailViewModel ttvm)
        {
            ttvm.IsBusy = false;
            //do nothing, gagal referesh ya wes
        }
        private void PostLoadTransaksis(List<TransaksiThumbnailViewModel> dbTransaksis)
        {
            //rekursif sampai semua diload
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            foreach (TransaksiThumbnailViewModel ttvm in dbTransaksis)
            {
                transaksis.Add(ttvm);
            }

            if (dbTransaksis.Count != pageSize)
            {
                //basis
                //sudah habis, done loading
                isAllLoaded = true;
                TransaksisCV.Refresh();
            }
            else
            {
                //rekurens
                ++pageLoaded;
                transaksiProvider.LazyFetchTransaksis(pageLoaded, PostLoadTransaksis);
            }
        }
        #endregion

        #region PrivateMethods.Saver
        /// <summary>
        /// post loader
        /// </summary>
        private void PostCancelTransaksi(TransaksiThumbnailViewModel result)
        {
        }
        #endregion
        #endregion
    }

}
